package com.bsoft.gol.hcs.utils;

import com.alibaba.fastjson.JSONObject;
import com.bs.util.ResultCode;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.constants.Style;
import org.apache.axis.constants.Use;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.description.ParameterDesc;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

public class WebServiceUtil {
    private final static Logger logger = LoggerFactory.getLogger(WebServiceUtil.class);
    private static final String WebServiceURLConfig="http://155.156.130.111:7791/hai/WebServiceEntry_new?wsdl";
    private static final String NAMESPACEURI = "http://tempuri.org/";
    private static final String XMLSCHEMAURL = "http://www.w3.org/2001/XMLSchema";
    private static final String WEBSERVICEURL = "http://219.146.149.178:10084/";
    //private static final String WEBSERVICEURL = "http://192.168.100.2:10084/";

    public static JSONObject getAppointMentServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"AppointMentService";
        String spaceName = "http://tempuri.org/IAppointMentService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getRegisterServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"RegisterService";
        String spaceName = "http://tempuri.org/IRegisterService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getCheckReportServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"CheckReportService";
        String spaceName = "http://tempuri.org/ICheckReportService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getInspectionReportServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"InspectionReportService";
        String spaceName = "http://tempuri.org/IInspectionReportService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getQueuesServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"QueuesService";
        String spaceName = "http://tempuri.org/IQueuesService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getOutPatientServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"OutPatientService";
        String spaceName = "http://tempuri.org/IOutPatientService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getHospitalizationServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"HospitalizationService";
        String spaceName = "http://tempuri.org/IHospitalizationService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getQueryServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"QueryService";
        String spaceName = "http://tempuri.org/IQueryService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getPaymentServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"PaymentService";
        String spaceName = "http://tempuri.org/IPaymentService/";//cxf空间名
        JSONObject res = getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
        return res;
    }

    public static JSONObject getAntibacterialServiceMethod(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        String endPoint = WEBSERVICEURL+"AntibacterialService";
        String spaceName = "http://tempuri.org/IAntibacterialService/"; //cxf空间名
        return getServiceValues(queryConditions,wsMethodName,endPoint,spaceName);
    }


    public static JSONObject getServiceValues(LinkedHashMap<String, Object> queryConditions, String wsMethodName, String endPoint, String spaceName){
        //设置组织机构代码
        queryConditions.put("hospitalCode","1");
        logger.info("service---------------------:{}",wsMethodName);
        logger.info("{}入参:{}",wsMethodName,queryConditions.toString());
        Date begin = new Date();
        JSONObject res = new JSONObject();
        Object[] objectValue = getObjectValue(queryConditions);
        OperationDesc oper = getOperation(queryConditions,wsMethodName);
        Service service = new Service();
        try {
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(endPoint);
            call.setOperation(oper);
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(spaceName + wsMethodName);
            call.setEncodingStyle(null);
            call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
            call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
            call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
            call.setOperationName(new javax.xml.namespace.QName(NAMESPACEURI, wsMethodName));
            call.setOperationName(new javax.xml.namespace.QName(NAMESPACEURI, wsMethodName));
            String str = null;
            try {
                str = (String) call.invoke(objectValue);
            } catch (RemoteException e) {
                e.printStackTrace();
                logger.error("WebServiceUtil "+ wsMethodName + " error.", e);
            }
            logger.info("{}返回值:{}",service,str);
            if(null!=str){
                res= JSONObject.parseObject(str);
            }
        } catch (ServiceException e) {
            e.printStackTrace();
            logger.error("WebServiceUtil "+ wsMethodName + " error.", e);
        }
        logger.info("{}返回值json:{}",service,res.toJSONString());
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        logger.info("——————————"+simpleDateFormat.format(new Date())+"(" + service + ")耗费时间：" + (new Date().getTime() - begin.getTime()) + "毫秒——————————");
        return res;
    }


    public static OperationDesc getOperation(LinkedHashMap<String, Object> queryConditions, String wsMethodName){
        OperationDesc oper = new OperationDesc();
        ParameterDesc param = new ParameterDesc();
        oper.setName(wsMethodName);
        for(Map.Entry<String, Object> entry: queryConditions.entrySet())
        {
            if(null == entry.getValue()){
                entry.setValue("");
            }
            if(entry.getValue().getClass().equals(String.class)){
                param = new ParameterDesc(new QName(NAMESPACEURI, entry.getKey()),ParameterDesc.IN, new QName(XMLSCHEMAURL, "string"), java.lang.String.class, false, false);
                param.setOmittable(true);
                param.setNillable(true);
                oper.addParameter(param);
            }else if(entry.getValue().getClass().equals(Integer.class)){
                param = new ParameterDesc(new QName(NAMESPACEURI, entry.getKey()), ParameterDesc.IN, new QName(XMLSCHEMAURL, "int"), Integer.class, false, false);
                param.setOmittable(true);
                oper.addParameter(param);
            }else{
                param = new ParameterDesc(new QName(NAMESPACEURI, entry.getKey()),ParameterDesc.IN, new QName(XMLSCHEMAURL, "string"), java.lang.String.class, false, false);
                param.setOmittable(true);
                param.setNillable(true);
                oper.addParameter(param);
            }
        }
        oper.setReturnType(new QName(XMLSCHEMAURL, "string"));
        oper.setReturnClass(java.lang.String.class);
        oper.setReturnQName(new QName(NAMESPACEURI, wsMethodName+"Result"));
        oper.setStyle(Style.WRAPPED);
        oper.setUse(Use.LITERAL);

        return oper;
    }

    public static Object[] getObjectValue(LinkedHashMap<String, Object> queryConditions){
        int size = queryConditions.size();
        Object[] objectValue = new Object[size];
        int i=0;
        for(Map.Entry<String, Object> entry: queryConditions.entrySet())
        {
            objectValue[i] =  entry.getValue();
            if(null == entry.getValue()){
                entry.setValue("");
            }
            i++;
        }
        return objectValue;
    }


    public static JSONObject openWSDL(String startUrl, String xml) {
        if (startUrl == null || "".equals(startUrl)) {
            startUrl =WebServiceURLConfig;
            logger.info("his连接地址为{}", startUrl);
        }
        logger.info("开始获取服务,地址：{},参数：{}", startUrl, xml);
        Date begin = new Date();
        StringBuilder sb = null;
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        String result = null;
        org.json.JSONObject json = null;
        JSONObject res= null;
        try {
            URL url = new URL(startUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(30000);
            connection.setReadTimeout(30000);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setChunkedStreamingMode(0);
            OutputStream os = connection.getOutputStream();
            os.write(xml.getBytes());
            int responseCode = connection.getResponseCode();
            String tempString = null;
            if (200 == responseCode) {
                is = connection.getInputStream();
                isr = new InputStreamReader(is,"UTF-8");
                br = new BufferedReader(isr);
                sb = new StringBuilder();
                String temp;
                while (null != (temp = br.readLine())) {
                    sb.append(temp);
                }
                logger.info("{}获取服务成功", startUrl);
            } else {
                logger.warn("获取服务异常,responseCode{}", Integer.valueOf(responseCode));

//                BufferedReader reader = new BufferedReader(
//                        new InputStreamReader(connection.getErrorStream(),
//                                "UTF-8"));
//                // 一次读入一行，直到读入null为文件结束
//                while ((tempString = reader.readLine()) != null) {
//                    sb.append(tempString);
//                }
//                if (null != reader) {
//                    reader.close();
//                }
            }
            os.close();
            if (sb != null) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                result = ((String) Objects.requireNonNull(Dom4jUtil.readStringXml(String.valueOf(sb)))).replaceAll("},\"\"", "}").replaceAll("&lt;", "").replaceAll("&amp;","").replace("\"\",\"\"", "");
                logger.info("===返回值=={}", result);
                res = new JSONObject();
                res = JSONObject.parseObject(XmlToJson.xml2jsonString(result));
                logger.info("===json返回值=={}", res);
                logger.info("——————————" + simpleDateFormat.format(new Date()) + "耗费时间：" + (System.currentTimeMillis() - begin.getTime()) + "毫秒——————————");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    public static JSONObject openWSDL2(String startUrl, String xml) {
        if (startUrl == null || "".equals(startUrl)) {
            startUrl = WebServiceURLConfig;
            // logger.info("his连接地址为{}", startUrl);
        }
        logger.info("开始获取服务,地址：{},参数：{}", startUrl, xml);
        Date begin = new Date();
        StringBuilder sb = null;
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        String result = null;
        org.json.JSONObject json = null;
        JSONObject res = new JSONObject();
        try {
            URL url = new URL(startUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(30000);
            connection.setReadTimeout(30000);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setChunkedStreamingMode(0);
            OutputStream os = connection.getOutputStream();
            os.write(xml.getBytes("UTF-8"));
            int responseCode = connection.getResponseCode();
            String tempString = null;
            if (200 == responseCode) {
                is = connection.getInputStream();
                isr = new InputStreamReader(is,"UTF-8");
                br = new BufferedReader(isr);
                sb = new StringBuilder();
                String temp;
                while (null != (temp = br.readLine())) {
                    sb.append(temp);
                }
                // logger.info("{}获取服务成功", startUrl);
            } else {
                logger.warn("获取服务异常,responseCode{}", Integer.valueOf(responseCode));
                logger.warn("获取服务异常,responseMessage{}", IOUtils.toString(connection.getErrorStream(), StandardCharsets.UTF_8));
                res.put("code", Integer.valueOf(responseCode));
                res.put("message","网络延迟，刷新重试");

//                BufferedReader reader = new BufferedReader(
//                        new InputStreamReader(connection.getErrorStream(),
//                                "UTF-8"));
//                // 一次读入一行，直到读入null为文件结束
//                while ((tempString = reader.readLine()) != null) {
//                    sb.append(tempString);
//                }
//                if (null != reader) {
//                    reader.close();
//                }
            }
            os.close();
            if (sb != null) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                result = ((String) Objects.requireNonNull(Dom4jUtil.readStringXml(String.valueOf(sb)))).replaceAll("},\"\"", "}").replaceAll("&lt;", "").replaceAll("&amp;","").replace("\"\",\"\"", "");
                //logger.info("===返回值=={}", result);
                //res = new JSONObject();
                res = JSONObject.parseObject(result);
                //logger.info("===json返回值=={}", res);
                // logger.info("——————————" + simpleDateFormat.format(new Date()) + "耗费时间：" + (System.currentTimeMillis() - begin.getTime()) + "毫秒——————————");
                if(res.isEmpty()){
                    res.put("code", ResultCode.SUCCESS);
                    res.put("message","返回值为空");
                }
            }
        } catch (Exception e) {
            logger.info("异常"+e);
            res.put("code",Constants.ERR_CODE);
            res.put("message","获取服务异常");
        }
        return res;
    }

}
